import { ShapeGeometry, Group as TGroup, Mesh, DoubleSide, BufferGeometry, BufferAttribute, ShaderMaterial } from "three";
import { CompoundPath, Group as ZGroup, Polygon } from "zrender";
import { CqkjMap } from "../Basic/CqkjMap";
import { MapElement, MapElementOption } from "../Basic/MapElement";
import { projection } from "../Util/projection";

export class ForeignAirspace extends MapElement<MapElementOption>{
  root2 = new ZGroup()
  root3 = new TGroup()
  // mesh: Mesh<ShapeGeometry, ShaderMaterial>;
  // path: CompoundPath;

  get mesh() {
    return this.root3.children[0] as Mesh<ShapeGeometry, ShaderMaterial>
  }

  get path() {
    return this.root2.childAt(0) as CompoundPath
  }

  get show(): boolean {
    return this.option.show
  }
  set show(val: boolean) {
    if (this.option.show != val) {
      this.option.show = val
      this.root3.visible = val
      val ? this.root2.show() : this.root2.hide()
    }
  }

  constructor(map: CqkjMap, data: number[][][][]) {
    super(map, {
      name: '国外领空',
      show: true
    })
    const { root2, root3 } = this
    const points = data.map(e => e.map(e => e.map(e => [projection.lonToX(e[0]), projection.latToY(e[1])])))
    const mesh = new Mesh(createGeometry(points), new ShaderMaterial({
      transparent: true,
      side: DoubleSide,
      depthTest: false,
      depthWrite: false,
      vertexShader: `
      varying float v_a;
      void main(){
        vec4 mPosition=modelMatrix  * vec4(position,1.0);
        v_a=mPosition.z/mPosition.w/280000.0;
        gl_Position=projectionMatrix * viewMatrix * mPosition;
      }
      `,
      fragmentShader: `
      varying float v_a;
      void main(){
        float a=max(0.1,(abs(v_a-0.5)-0.4)*10.0);
        gl_FragColor=vec4(1.0,0.0,0.0,a);
      }
      `
    }))
    root3.add(mesh)
    map.scene.add(root3)

    const path = createCompoundPath(points)
    root2.add(path)
    map.ground.root.add(root2)
    this.onModeChange()
  }

  onModeChange(): void {
    if(this.map.mode=='2D'){
      this.mesh.visible=false
      this.path.attr({
        style:{
          lineWidth:1
        }
      })
    }else{
      this.mesh.visible=true
      this.path.attr({
        style:{
          lineWidth:0
        }
      })
    }
  }

  onDestroy(): void {
    const { mesh, path } = this
    this.map.scene.remove(mesh)
    this.map.ground.root.remove(path)
    mesh.geometry.dispose()
    mesh.material.dispose()
  }

}



function createGeometry(polygons: number[][][][]) {

  const geometry = new BufferGeometry()
  const position: number[] = []
  const index: number[] = []
  let k = 0
  polygons.forEach(lines => {
    lines.forEach(points => {
      points.forEach((p, i) => {
        if (i) {
          const k2 = k * 2
          index.push(k2 - 2, k2, k2 - 1, k2, k2 + 1, k2 - 1)
        }
        position.push(p[0], p[1], 0, p[0], p[1], 280000)
        k++
      })
    })
  })

  geometry.attributes.position = new BufferAttribute(new Float32Array(position), 3)
  geometry.index = new BufferAttribute(new Uint16Array(index), 1)

  return geometry
}

function createCompoundPath(polygons: number[][][][]) {
  const paths: Polygon[] = []
  polygons.forEach(lines => {
    lines.forEach(points => {
      paths.push(new Polygon({
        shape: {
          points
        }
      }))
    })
  })
  return new CompoundPath({
    z: 5,
    shape: {
      paths
    },
    style: {
      fill: '#ff0000',
      fillOpacity: 0.1,
      stroke: '#ff0000',
      strokeNoScale: true,
      lineWidth: 1
    }
  })
}